#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
短信验证码服务（模拟版）
用于开发测试，实际生产环境需要对接真实的短信服务商
"""

import random
import time
import logging
from datetime import datetime, timedelta
from django.core.cache import cache

logger = logging.getLogger(__name__)


class SMSService:
    """短信服务类（模拟）"""
    
    # 验证码有效期（秒）
    CODE_EXPIRE_TIME = 300  # 5分钟
    
    # 发送间隔限制（秒）
    SEND_INTERVAL = 60  # 60秒内不能重复发送
    
    @staticmethod
    def generate_code(length=6):
        """
        生成随机验证码
        :param length: 验证码长度
        :return: 验证码字符串
        """
        return ''.join([str(random.randint(0, 9)) for _ in range(length)])
    
    @staticmethod
    def get_cache_key(phone, code_type='register'):
        """
        获取缓存key
        :param phone: 手机号
        :param code_type: 验证码类型 (register-注册, login-登录, reset-重置密码)
        :return: 缓存key
        """
        return f'sms_code:{code_type}:{phone}'
    
    @staticmethod
    def get_last_send_key(phone, code_type='register'):
        """获取上次发送时间的缓存key"""
        return f'sms_last_send:{code_type}:{phone}'
    
    @classmethod
    def send_code(cls, phone, code_type='register'):
        """
        发送验证码（模拟）
        :param phone: 手机号
        :param code_type: 验证码类型
        :return: (success, message, code)
        """
        # 检查发送频率
        last_send_key = cls.get_last_send_key(phone, code_type)
        last_send_time = cache.get(last_send_key)
        
        if last_send_time:
            elapsed = time.time() - last_send_time
            if elapsed < cls.SEND_INTERVAL:
                wait_time = int(cls.SEND_INTERVAL - elapsed)
                return False, f'发送过于频繁，请{wait_time}秒后再试', None
        
        # 生成验证码
        code = cls.generate_code()
        
        # 存储验证码到缓存
        cache_key = cls.get_cache_key(phone, code_type)
        cache.set(cache_key, code, cls.CODE_EXPIRE_TIME)
        
        # 记录发送时间
        cache.set(last_send_key, time.time(), cls.SEND_INTERVAL)
        
        # 模拟发送短信（实际应该调用短信服务商API）
        logger.info(f'[模拟短信] 发送验证码到 {phone}: {code} (类型: {code_type})')
        
        # 开发环境：直接返回验证码；生产环境：不应返回
        return True, '验证码已发送', code
    
    @classmethod
    def verify_code(cls, phone, code, code_type='register'):
        """
        验证验证码
        :param phone: 手机号
        :param code: 用户输入的验证码
        :param code_type: 验证码类型
        :return: (success, message)
        """
        if not phone or not code:
            return False, '手机号或验证码不能为空'
        
        # 从缓存获取验证码
        cache_key = cls.get_cache_key(phone, code_type)
        stored_code = cache.get(cache_key)
        
        if not stored_code:
            return False, '验证码已过期或不存在'
        
        # 验证码比对
        if str(stored_code) != str(code):
            return False, '验证码错误'
        
        # 验证成功后删除验证码（防止重复使用）
        cache.delete(cache_key)
        
        logger.info(f'验证码验证成功: {phone} (类型: {code_type})')
        return True, '验证成功'
    
    @classmethod
    def get_code_for_debug(cls, phone, code_type='register'):
        """
        获取当前验证码（仅用于调试）
        生产环境应该删除此方法
        :param phone: 手机号
        :param code_type: 验证码类型
        :return: 验证码或None
        """
        cache_key = cls.get_cache_key(phone, code_type)
        return cache.get(cache_key)


# 验证码类型常量
class SMSCodeType:
    REGISTER = 'register'    # 注册
    LOGIN = 'login'          # 登录
    RESET_PASSWORD = 'reset' # 重置密码
    BIND_PHONE = 'bind'      # 绑定手机


# 便捷函数
def send_register_code(phone):
    """发送注册验证码"""
    return SMSService.send_code(phone, SMSCodeType.REGISTER)


def send_login_code(phone):
    """发送登录验证码"""
    return SMSService.send_code(phone, SMSCodeType.LOGIN)


def send_reset_password_code(phone):
    """发送重置密码验证码"""
    return SMSService.send_code(phone, SMSCodeType.RESET_PASSWORD)


def verify_register_code(phone, code):
    """验证注册验证码"""
    return SMSService.verify_code(phone, code, SMSCodeType.REGISTER)


def verify_login_code(phone, code):
    """验证登录验证码"""
    return SMSService.verify_code(phone, code, SMSCodeType.LOGIN)


def verify_reset_password_code(phone, code):
    """验证重置密码验证码"""
    return SMSService.verify_code(phone, code, SMSCodeType.RESET_PASSWORD)


